package namespace

import (
	"errors"
	"fmt"
	"sort"

	"gddgame.cc/galaxy/binocle"
	"gddgame.cc/galaxy/binocle/module/report"
	. "gddgame.cc/galaxy/common/dsl/game"
	. "gddgame.cc/galaxy/common/dsl/game/ad"
	. "gddgame.cc/galaxy/common/dsl/game/user"
	. "gddgame.cc/galaxy/common/dsl/web"
	"gddgame.cc/galaxy/common/namespaces"
	"gddgame.cc/galaxy/common/namespaces/cooperate"
	"gddgame.cc/galaxy/common/namespaces/cooperate/structure"
	"gddgame.cc/galaxy/core/sdk"
	"gddgame.cc/galaxy/project/breeder/breeder/center"
	"gddgame.cc/galaxy/project/breeder/breeder/controller"
	"gddgame.cc/galaxy/project/breeder/breeder/cooperated"
	"gddgame.cc/galaxy/project/breeder/breeder/model"
	"gddgame.cc/galaxy/satellite/formula/nebula"
	"gddgame.cc/galaxy/server/composer"
	"gddgame.cc/galaxy/utils"
	"gddgame.cc/galaxy/utils/def"
	"gddgame.cc/galaxy/utils/serialize"
)

const (
	InfoSelf nebula.NSE = iota
	InfoUser
	InfoStat
	InfoFriend
	InfoFriendInvited
	InfoSearch
	InfoRank
	InfoRequestAd
	InfoResponseAd
	InfoReceiveReward
	InfoProps
	InfoUseProp
	InfoSellProp
	InfoPutOnProp
	InfoPutOutProp
	InfoEquips
	InfoIntensifyEquip
	InfoDismantleEquip
	InfoPutOnEquip
	InfoPutOutEquip
	InfoUnits
	InfoUnitDetail
	InfoUnitCurrent
	InfoUpgradeUnitPower
	InfoResetUnitPower
	InfoUnitGo
	InfoUnitDown
	InfoUnitCreate
	InfoUnitDelete
	InfoUnitChangeTargetMode
	InfoUnitChangeAiMode
	InfoScienceUp
	InfoShopProps
	InfoBuyShopProps
	InfoOperationList
	InfoOperate
	InfoCanUnitList
	InfoCanUnitBuildList
	InfoUnitSort
	InfoUnitGroup
	// todo 联盟操作

	InfoBuildUpgrade        = 100
	InfoBuildDestroy        = 101
	InfoUnitMove            = 102
	InfoUnitFly             = 103
	InfoUnitToRobot         = 104
	InfoUseDirect           = 105
	InfoUseDirectWithTarget = 106
	InfoBuildCreate         = 107
	InfoUnitPut             = 108

	InfoOnReceive    = 200
	InfoOnUnitChange = 201
	InfoOnError      = 202
)

func GetInfoQueryParam(context def.Context) (mapNoId string, accountId int, selfIdentity int, err error) {
	if err = context.Get("map_no_id", &mapNoId); err != nil {
		return
	}
	if err = context.Get("account_id", &accountId); err != nil {
		return
	}
	if err = context.Get("identity", &selfIdentity); err != nil {
		return
	}
	return
}

/*
 游戏信息加载
*/
func InfoHandler(builder composer.Builder, client *sdk.AppClient, namespace nebula.Namespace, delegate *Delegate) {
	var agent binocle.App
	builder.Factory("agent", &agent)

	namespace.SetCompress(false)

	reporter := agent.AddMetrics().Period(report.Minute1).Type(report.BothMetric).
		Aggregate(report.Sum, report.Max).Reporter()

	if err := namespace.Connect(func(socket *nebula.Socket, next nebula.Next) {
		var openId string
		err := socket.Get("open_id", &openId)
		if err != nil {
			fmt.Println(err)
			_ = next(errors.New("Auth error"))
			return
		}
		_ = next(nil)

	}); err != nil {
		builder.Error(err)
	}

	cooperateNS, _ := namespace.Root().Of(COOPERATE)

	_ = cooperateNS.On(namespaces.CooperateInlineCreate, func(req *nebula.Request, t byte, id interface{}) {
		//fmt.Println("info create", t, id)
		var rr *nebula.Request
		switch structure.PublicDataType(t) {
		case cooperated.UnitType:
			_ = req.Get("create_unit_"+utils.ToString(id), &rr)
			//fmt.Println(err, rr)

			if rr != nil {
				rr.Response(true)
			}
		}
	})
	_ = cooperateNS.On(namespaces.CooperateInlineNotice, func(req *nebula.Request, event byte, content []byte) {
		// 下发通知
		switch event {
		case center.PickUpReceiveNoticeEvent:
			var dd model.DataRelationShowSlice
			slot := serialize.GetSlot()
			_ = slot.Set(&dd)
			_ = slot.Unmarshal(content)
			req.Namespace(namespace)
			if err := req.Emit(InfoOnReceive, dd); err != nil {
				fmt.Println(err)
			}
			slot.Release()
		case center.UnitChangeNoticeEvent:
			req.Namespace(namespace)
			if err := req.Emit(InfoOnUnitChange); err != nil {
				fmt.Println(err)
			}
		case center.ErrorNoticeEvent:
			req.Namespace(namespace)
			if err := req.Emit(InfoOnError, utils.ToString(content)); err != nil {
				fmt.Println(err)
			}
		}
	})

	_ = namespace.On(InfoSelf, func(req *nebula.Request) {
		var openId string
		var user model.User
		if err := req.Get("open_id", &openId); err != nil {
			return
		}
		_ = controller.Env.RefreshUserStatus(openId, false)
		language := GetLanguage(req)
		detail, err := controller.Center.GetUserDetail(openId, &user, language)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		mapNoId, _, _, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		account := controller.Center.GetData(mapNoId, cooperated.AccountType, user.AccountId)
		stat := controller.Center.GetStatData(account)
		userDetail, err := controller.GetUserDetailInfo(req, &user, account.(*cooperated.Account), stat)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		userDetail.BindGameUser(detail)

		req.SetCompress(true)

		req.Response(detail)
	})

	_ = namespace.On(InfoUser, func(req *nebula.Request, targetId string) {
		var openId string
		if err := req.Get("open_id", &openId); err != nil {
			req.ResponseErr(err)
			return
		}
		var user model.User
		language := GetLanguage(req)
		info, err := controller.Center.GetUserInfo(openId, targetId, &user, language)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		extend, err := controller.GetUserPublicInfo(req, &user, language)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		extend.BindGameUser(info)
		req.SetCompress(true)
		req.Response(info)
	})

	_ = namespace.On(InfoStat, func(req *nebula.Request, key string, value int) {
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		_ = controller.Center.UpdateStatSingle(req, &user, controller.Center.StatData, key, int32(value), false)

		req.Response(true)
	})

	_ = namespace.On(InfoFriend, func(req *nebula.Request, updateTime int) {
		// 获取好友信息
		var openId string
		if err := req.Get("open_id", &openId); err != nil {
			return
		}
		t := GetUpdateTime(req, updateTime)
		language := GetLanguage(req)
		var userList []model.User
		var gameUserList []*model.GameOtherUserExtend
		list, err := controller.Center.GetFriendList(openId, t, func(openIds []string) []UserBase {
			_ = controller.Center.FindUsers(openIds, "", nil, &userList)
			users := make([]UserBase, len(userList))
			gameUserList = make([]*model.GameOtherUserExtend, len(userList))
			var err error
			for index, u := range userList {
				if gameUserList[index], err = controller.GetUserPublicInfo(req, &u, language); err != nil {
					fmt.Println(err)
				}
				users[index] = &u
			}
			return users
		}, language, true)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		for index, u := range gameUserList {
			u.BindGameUser(list[index])
		}
		req.SetCompress(true)
		req.Response(list)
	})
	_ = namespace.On(InfoFriendInvited, func(req *nebula.Request, updateTime int) {
		// 获取好友信息
		var openId string
		if err := req.Get("open_id", &openId); err != nil {
			return
		}
		t := GetUpdateTime(req, updateTime)
		language := GetLanguage(req)
		var userList []model.User
		var gameUserList []*model.GameOtherUserExtend
		list, err := controller.Center.GetFriendList(openId, t, func(openIds []string) []UserBase {
			_ = controller.Center.FindUsers(openIds, "", nil, &userList)
			users := make([]UserBase, len(userList))
			gameUserList = make([]*model.GameOtherUserExtend, len(userList))
			for index, u := range userList {
				gameUserList[index], _ = controller.GetUserPublicInfo(req, &u, language)
				users[index] = &u
			}
			return users
		}, language, false)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		for index, u := range gameUserList {
			u.BindGameUser(list[index])
		}
		req.SetCompress(true)
		req.Response(list)
	})
	_ = namespace.On(InfoSearch, func(req *nebula.Request, keyword string) {
		var openId string
		if err := req.Get("open_id", &openId); err != nil {
			return
		}
		language := GetLanguage(req)
		var userList []model.User
		var gameUserList []*model.GameOtherUserExtend
		list, err := controller.Center.GetSearchList(openId, keyword, func(openIds []string) []UserBase {
			_ = controller.Center.FindUsers(openIds, keyword, nil, &userList)
			users := make([]UserBase, len(userList))
			gameUserList = make([]*model.GameOtherUserExtend, len(userList))
			for index, u := range userList {
				gameUserList[index], _ = controller.GetUserPublicInfo(req, &u, language)
				users[index] = &u
			}
			return users
		}, language)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		for index, u := range gameUserList {
			u.BindGameUser(list[index])
		}
		req.SetCompress(true)
		req.Response(list)
	})

	_ = namespace.On(InfoRank, func(req *nebula.Request, rankKey string, number int) {
		var openId string
		if err := req.Get("open_id", &openId); err != nil {
			return
		}
		language := GetLanguage(req)
		var userList []model.User
		var gameUserList []*model.GameOtherUserExtend
		list, err := controller.Center.GetRankList(openId, rankKey, number, func(openIds []string) []UserBase {
			_ = controller.Center.FindUsers(openIds, "", nil, &userList)
			users := make([]UserBase, len(userList))
			gameUserList = make([]*model.GameOtherUserExtend, len(userList))
			for index, u := range userList {
				gameUserList[index], _ = controller.GetUserPublicInfo(req, &u, language)
				users[index] = &u
			}
			return users
		}, language)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		for index, u := range gameUserList {
			u.BindRankUser(list[index])
		}
		req.SetCompress(true)
		req.Response(list)
	})
	_ = namespace.On(InfoRequestAd, func(req *nebula.Request, plane int) {
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			req.ResponseErr(err)
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		t, err := NextAd(controller.Env, user.OpenId, AdPlane(plane))
		if err != nil {
			req.ResponseErr(err)
			return
		}
		reporter.Increase("ad.plane.request." + string(t.Plane))
		reporter.Increase("ad.brand.request." + t.Brand)
		//fmt.Println(t)
		req.Response(t)
	})
	_ = namespace.On(InfoResponseAd, func(req *nebula.Request, plane int) {
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			req.ResponseErr(err)
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		t, err := NextAd(controller.Env, user.OpenId, AdPlane(plane))
		if err != nil {
			req.ResponseErr(err)
			return
		}
		if err := ResponseAd(controller.Env, user.OpenId, t); err != nil {
			req.ResponseErr(err)
			return
		}
		reporter.Increase("ad.plane.response." + string(t.Plane))
		reporter.Increase("ad.brand.response." + t.Brand)
		if err := controller.Center.UpdateStatSingle(req, &user, controller.Center.StatData, model.AdStat, 1, false); err != nil {
			req.ResponseErr(err)
			return
		}
		req.Response(true)
	})

	_ = namespace.On(InfoReceiveReward, func(req *nebula.Request, messageId int) {
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		reward, err := controller.ReceiveRewardMessage(req, &user, messageId)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		req.Response(reward)
	})
	// 道具列表
	_ = namespace.On(InfoProps, func(req *nebula.Request, updateTime int) {
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}

		var uProps []model.UserProp
		var err error
		uProps, err = controller.GetProps(req, userId, GetUpdateTime(req, updateTime))
		// 获取道具信息
		props := make([]*model.PlayerProp, len(uProps))
		for key := range uProps {
			props[key] = model.NewPlayerProp(&uProps[key])
		}
		if err != nil {
			req.ResponseErr(err)
			return
		}
		req.SetCompress(true)
		req.Response(props)
	})
	// 道具使用
	_ = namespace.On(InfoUseProp, func(req *nebula.Request, userPropId int) {
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		mapNoId, accountId, _, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		account := controller.Center.GetData(mapNoId, cooperated.AccountType, accountId)
		prop, err := controller.UseProp(req, userPropId, &user, account.(*cooperated.Account))
		if err != nil {

			req.ResponseErr(err)
			return
		}

		req.Response(prop.ReceiveSlice)
	})
	// 道具出售
	_ = namespace.On(InfoSellProp, func(req *nebula.Request, userPropId int, number int) {
		fmt.Println("info prop sell", userPropId, number)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		prop, err := controller.SellProp(req, userPropId, number, &user)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		req.Response(prop.SellReceive)
	})
	// 装上道具
	_ = namespace.On(InfoPutOnProp, func(req *nebula.Request, userPropId int, userUnitId string, index int, number int) {
		fmt.Println("info prop puton", userPropId, userUnitId, number)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}

		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		account := controller.Center.GetData(mapNoId, cooperated.AccountType, accountId)
		unit := controller.Center.GetData(mapNoId, cooperated.UnitType, userUnitId)
		userUnit, err := controller.GetUnitWithUser(req, userUnitId, &user)
		if err != nil {
			return
		}
		if userUnit.Index >= 0 {
			req.ResponseErr(errors.New("部队作战中"))
			return
		}
		if err := controller.PutOnProp(req, userPropId, index, number, &user, account.(*cooperated.Account), userUnit, unit.(*cooperated.Unit)); err != nil {
			req.ResponseErr(err)
			return
		}
		_ = controller.SaveUnit(req, userUnit)

		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.Update, []interface{}{cooperated.UnitType, userUnit.Id, model.PropAbilitySource})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
	})
	// 卸下道具
	_ = namespace.On(InfoPutOutProp, func(req *nebula.Request, propId int, userUnitId string, index int) {
		fmt.Println("info prop putout", propId, userUnitId)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		userUnit, err := controller.GetUnitWithUser(req, userUnitId, &user)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		if userUnit.Index >= 0 {
			req.ResponseErr(errors.New("部队作战中"))
			return
		}
		if err := controller.PutOutProp(req, propId, index, &user, userUnit); err != nil {
			req.ResponseErr(err)
			return
		}
		if userUnit == nil {
			return
		}

		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}

		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.Update, []interface{}{cooperated.UnitType, userUnit.Id, model.PropAbilitySource})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
	})
	// 装备列表
	_ = namespace.On(InfoEquips, func(req *nebula.Request, updateTime int) {
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}

		var equips []*model.PlayerEquip
		var err error
		equips, err = controller.GetEquips(req, userId, GetUpdateTime(req, updateTime))
		if err != nil {
			req.ResponseErr(err)
			return
		}
		req.SetCompress(true)
		req.Response(equips)
	})
	// 强化装备, 如何强化，强化多少
	_ = namespace.On(InfoIntensifyEquip, func(req *nebula.Request, userEquipId int) {
		fmt.Println("info equip intensify", userEquipId)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}

		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}

		userEquip, err := controller.GetUserEquip(req, userEquipId, &user)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		account := controller.Center.GetData(mapNoId, cooperated.AccountType, accountId)
		var t *cooperated.Unit
		var userUnit *model.UserUnit
		if userEquip.UnitId != "" {
			userUnit, err = controller.GetUnitWithUser(req, userEquip.UnitId, &user)
			if err != nil {
				return
			}
			if userUnit.Index >= 0 {
				req.ResponseErr(errors.New("部队作战中"))
				return
			}
			unit := controller.Center.GetData(mapNoId, cooperated.UnitType, userEquip.UnitId)
			t = unit.(*cooperated.Unit)
		}
		if err := controller.IntensifyEquip(req, userEquip, &user, account.(*cooperated.Account), userUnit, t); err != nil {
			req.ResponseErr(err)
			return
		}

		if userUnit == nil {
			return
		}

		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.Update, []interface{}{cooperated.UnitType, userUnit.Id, model.EquipAbilitySource})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
	})
	// 分解装备，从哪个部队上
	_ = namespace.On(InfoDismantleEquip, func(req *nebula.Request, userEquipId int) {
		fmt.Println("info equip dismantle", userEquipId)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		_, err := controller.DismantleEquip(req, userEquipId, &user)
		if err != nil {
			req.ResponseErr(err)
			return
		}
	})
	// 装上装备
	_ = namespace.On(InfoPutOnEquip, func(req *nebula.Request, userEquipId int, userUnitId string, index int, location string) {
		fmt.Println("info equip puton", userEquipId, userUnitId, location)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		account := controller.Center.GetData(mapNoId, cooperated.AccountType, accountId)
		userUnit, err := controller.GetUnitWithUser(req, userUnitId, &user)
		if err != nil {
			return
		}
		if userUnit.Index >= 0 {
			req.ResponseErr(errors.New("部队作战中"))
			return
		}
		unit := controller.Center.GetData(mapNoId, cooperated.UnitType, userUnitId)
		if err := controller.PutOnEquip(req, userEquipId, index, location, &user, account.(*cooperated.Account), userUnit, unit.(*cooperated.Unit)); err != nil {
			req.ResponseErr(err)
			return
		}
		_ = controller.SaveUnit(req, userUnit)

		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.Update, []interface{}{cooperated.UnitType, userUnitId, model.EquipAbilitySource})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
	})
	// 写下装备
	_ = namespace.On(InfoPutOutEquip, func(req *nebula.Request, userEquipId int, userUnitId string) {
		fmt.Println("info equip putout", userEquipId)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}

		userUnit, err := controller.GetUnitWithUser(req, userUnitId, &user)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		if userUnit.Index >= 0 {
			req.ResponseErr(errors.New("部队作战中"))
			return
		}
		if err := controller.PutOutEquip(req, userEquipId, &user, userUnit); err != nil {
			req.ResponseErr(err)
			return
		}
		if userUnit == nil {
			return
		}
		_ = controller.SaveUnit(req, userUnit)

		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.Update, []interface{}{cooperated.UnitType, userUnit.Id, model.EquipAbilitySource})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
	})
	// 部队列表
	_ = namespace.On(InfoUnits, func(req *nebula.Request, updateTime int) {
		var userId int
		var err error
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		mapNoId, accountId, _, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		var units []*model.PlayerUnit
		list := controller.Center.ListDepend(mapNoId, cooperated.AccountType, accountId, cooperated.UnitDataType)
		if list == nil {
			req.Response([]*model.PlayerUnit{})
			return
		}
		ll := make(map[string]*cooperated.Unit, len(list))
		for _, t := range list {
			unit := t.(*cooperated.Unit)
			ll[unit.Id] = unit
		}

		units, err = controller.GetUnits(req, userId, GetUpdateTime(req, updateTime), ll)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		req.SetCompress(true)
		req.Response(units)
	})
	// 部队详情
	_ = namespace.On(InfoUnitDetail, func(req *nebula.Request, userUnitId string) {
		fmt.Println("info unit detail", userUnitId)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}

		var unitDetail *model.PlayerUnitDetail
		var err error

		mapNoId, _, _, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		info := controller.Center.GetData(mapNoId, cooperated.UnitType, userUnitId)
		if info == nil {
			req.ResponseErr(controller.Center.LanguageError("UNIT_NOT_EXIST"))
			return
		}
		unit, ok := info.(*cooperated.Unit)
		if !ok {
			req.ResponseErr(controller.Center.LanguageError("UNIT_NOT_EXIST"))
			return
		}
		userUnit, err := controller.GetUnitWithUser(req, userUnitId, &user)
		if err != nil {
			return
		}
		stat := controller.Center.GetStatData(unit)
		unitDetail, err = controller.GetUnitDetail(req, userUnit, unit, stat)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		req.SetCompress(true)
		req.Response(unitDetail)
	}) // 部队详情
	_ = namespace.On(InfoUnitCurrent, func(req *nebula.Request) {
		fmt.Println("info unit current")
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			fmt.Println(err)
			req.ResponseErr(err)
			return
		}
		var err error
		var userUnits []model.UserUnit

		userUnits, err = controller.GetCurrentUnit(req, userId)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		ids := make([]interface{}, len(userUnits))
		for index, userUnit := range userUnits {
			ids[index] = userUnit.Id
		}
		fmt.Println("current unit", ids)

		unitList := make([]*model.PlayerUnitDetail, len(ids))

		mapNoId, _, _, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		list := controller.Center.ListData(mapNoId, cooperated.UnitType, ids)
		if list == nil {
			req.ResponseErr(controller.Center.LanguageError("UNIT_NOT_EXIST"))
			return
		}
		fmt.Println("current unit", ids, list)
		for index, info := range list {
			unit, ok := info.(*cooperated.Unit)
			if !ok {
				req.ResponseErr(controller.Center.LanguageError("UNIT_NOT_EXIST"))
				return
			}
			stat := controller.Center.GetStatData(unit)
			unitDetail, err := controller.GetUnitDetail(req, &userUnits[index], unit, stat)
			if err != nil {
				req.ResponseErr(err)
				return
			}
			unitList[index] = unitDetail
		}
		req.SetCompress(true)
		req.Response(unitList)
	})
	// 设置部队天赋
	_ = namespace.On(InfoUpgradeUnitPower, func(req *nebula.Request, userUnitId string, powerId int) {
		fmt.Println("info unit upgrade power", userUnitId, powerId)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		userUnit, err := controller.GetUnitWithUser(req, userUnitId, &user)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		if userUnit.Index >= 0 {
			req.ResponseErr(errors.New("部队作战中"))
			return
		}
		account := controller.Center.GetData(mapNoId, cooperated.AccountType, accountId)
		unit := controller.Center.GetData(mapNoId, cooperated.UnitType, userUnitId)
		if err := controller.UpgradeUnitPower(req, powerId, &user, account.(*cooperated.Account), userUnit, unit.(*cooperated.Unit)); err != nil {
			req.ResponseErr(err)
			return
		}

		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.Update, []interface{}{cooperated.UnitType, userUnit.Id, model.PowerAbilitySource})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
	})

	// 重置部队天赋
	_ = namespace.On(InfoResetUnitPower, func(req *nebula.Request, userUnitId string) {
		fmt.Println("info unit reset power", userUnitId)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		userUnit, err := controller.GetUnitWithUser(req, userUnitId, &user)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		if userUnit.Index >= 0 {
			req.ResponseErr(errors.New("部队作战中"))
			return
		}
		if err := controller.ResetUnitPower(req, &user, userUnit); err != nil {
			req.ResponseErr(err)
			return
		}
		if userUnit == nil {
			return
		}
		_ = controller.SaveUnit(req, userUnit)

		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.Update, []interface{}{cooperated.UnitType, userUnit.Id, model.PowerAbilitySource})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
	})

	// 选择部队上场
	_ = namespace.On(InfoUnitGo, func(req *nebula.Request, userUnitId string, index int) {
		fmt.Println("info unit go", userUnitId, index)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		userUnit, err := controller.GetUnitWithUser(req, userUnitId, &user)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		if err := controller.GoUnit(req, index, &user, userUnit); err != nil {
			req.ResponseErr(err)
			return
		}
		if userUnit == nil {
			return
		}
		_ = controller.SaveUnit(req, userUnit)
		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.Update, []interface{}{cooperated.UnitType, userUnit.Id})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
	})

	// 选择部队下场
	_ = namespace.On(InfoUnitDown, func(req *nebula.Request, userUnitId string) {
		fmt.Println("info unit down", userUnitId)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}

		userUnits, err := controller.GetUnitsByIds(req, userId, []string{userUnitId})
		if err != nil {
			req.ResponseErr(err)
		}
		for _, unit := range userUnits {
			if unit.Index < 0 {
				req.ResponseErr(ValidException("部队未部署"))
				return
			}
		}
		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.DownUnit, []interface{}{[]string{userUnitId}})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		userUnit, err := controller.GetUnitWithUser(req, userUnitId, &user)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		if err := controller.ChangeUnitIndex(req, -1, &user, userUnit); err != nil {
			req.ResponseErr(err)
			return
		}
		controller.Center.PushNotice(mapNoId, accountId, center.UnitChangeNoticeEvent, nil)

		req.Response(true)
	})

	// 创建部队
	_ = namespace.On(InfoUnitCreate, func(req *nebula.Request, name string, unitId int) {
		fmt.Println("info unit create", name, unitId)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		key := controller.Center.TargetKeyMap[cooperated.UnitType][unitId]
		userUnit := &model.UserUnit{}
		id := controller.Center.TargetIdMap[cooperated.UnitType][key]
		unit := controller.Center.UnitMap[id]
		if name == "" {
			name = unit.Name
		}
		userUnit.Name = name
		userUnit.UserId = userId
		userUnit.UnitId = unitId
		userUnit.Level = 1
		userUnit.Index = -1

		ok, consumeData := controller.ValidConsume(req, unit.Levels[0].ConsumeSlice, 1, &user, userUnit)
		if !ok {
			req.ResponseErr(ValidException("购买所需不足"))
			return
		}
		if err := controller.UpdateConsume(req, consumeData, &user, userUnit); err != nil {
			req.ResponseErr(err)
			return
		}

		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.CreateUnit, []interface{}{key, nil, name})

		if result != nil {
			switch r := result.(type) {
			case error:
				req.ResponseErr(r)
				return
			}
			req.Async()
			_ = req.Set("create_unit_"+utils.ToString(result), req)
			userUnit.Id = utils.ToString(result)
			_ = controller.SaveUnit(req, userUnit)
		} else {
			req.Response(false)
		}
	})

	// 删除部队
	_ = namespace.On(InfoUnitDelete, func(req *nebula.Request, userUnitId string) {
		fmt.Println("info unit delete", userUnitId)
		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.Destroy, []interface{}{cooperated.UnitType, userUnitId})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
		_ = controller.DeleteUnit(req, userUnitId)
		// 清理工作？
	})

	// 移动部队
	_ = namespace.On(InfoUnitMove, func(req *nebula.Request, userUnitId string, moveMode byte, dataType byte, id interface{}) {
		fmt.Println("info unit move", userUnitId, moveMode, dataType, id)
		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.MoveUnit, []interface{}{userUnitId, moveMode, dataType, id})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
	})

	// 传送部队
	_ = namespace.On(InfoUnitFly, func(req *nebula.Request, userUnitId string, position []byte, nextPosition []byte) {
		fmt.Println("info unit fly", userUnitId, position)
		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}

		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.FlyUnit, []interface{}{userUnitId, position, nextPosition})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
	})

	// 部队托管
	_ = namespace.On(InfoUnitToRobot, func(req *nebula.Request, userUnitId string, position []byte, flag bool) {
		fmt.Println("info unit robot", userUnitId, position)
		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.RobotUnit, []interface{}{userUnitId, position, flag})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
	})

	// 投放部队
	_ = namespace.On(InfoUnitPut, func(req *nebula.Request, userUnitIds []string, position []byte, group int) {
		fmt.Println("info unit put", userUnitIds, position)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		userUnits, err := controller.GetUnitsByIds(req, userId, userUnitIds)
		if err != nil {
			req.ResponseErr(err)
		}
		for _, unit := range userUnits {
			if unit.Index >= 0 {
				req.ResponseErr(ValidException("部队已经部署"))
				return
			}
		}

		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.PutUnit, []interface{}{userUnitIds, position})
		if result != nil {
			switch t := result.(type) {
			case error:
				req.ResponseErr(t)
				return
			}
		}
		userCurrent, err := controller.GetCurrentUnit(req, userId)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		count := len(userCurrent)
		for i, _ := range userUnits {
			userUnits[i].Index = count + i
			userUnits[i].Group = group
			_ = controller.SaveUnit(req, &userUnits[i])
		}
		controller.Center.PushNotice(mapNoId, accountId, center.UnitChangeNoticeEvent, nil)
		req.Response(result)
	})

	// 部队修改ai策略
	_ = namespace.On(InfoUnitChangeTargetMode, func(req *nebula.Request, userUnitId string, targetMode int) {
		fmt.Println("info unit change target mode", userUnitId, targetMode)
		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		//if _, err := controller.ChangeUnitTargetMode(req, userUnitId, targetMode, &user); err != nil {
		//	return
		//}
		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.ChangeTargetMode, []interface{}{userUnitId, targetMode})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
	})
	_ = namespace.On(InfoUnitChangeAiMode, func(req *nebula.Request, userUnitId string, aiMode int) {
		fmt.Println("info unit change ai mode", userUnitId, aiMode)
		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		//if _, err := controller.ChangeUnitAiMode(req, userUnitId, aiMode, &user); err != nil {
		//	return
		//}
		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.ChangeAiMode, []interface{}{userUnitId, aiMode})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
	})
	// 部队修改部署索引
	_ = namespace.On(InfoUnitSort, func(req *nebula.Request, userUnitId string, index int) {
		fmt.Println("info unit change index", userUnitId, index)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		userUnit, err := controller.GetUnitWithUser(req, userUnitId, &user)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		if err := controller.ChangeUnitIndex(req, index, &user, userUnit); err != nil {
			return
		}
		mapNoId, accountId, _, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		controller.Center.PushNotice(mapNoId, accountId, center.UnitChangeNoticeEvent, nil)
		req.Response(true)
	})

	// 部队修改编组
	_ = namespace.On(InfoUnitGroup, func(req *nebula.Request, userUnitId string, group int) {
		fmt.Println("info unit change group", userUnitId, group)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		userUnit, err := controller.GetUnitWithUser(req, userUnitId, &user)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		if err := controller.ChangeUnitGroup(req, group, &user, userUnit); err != nil {
			return
		}
		mapNoId, accountId, _, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		controller.Center.PushNotice(mapNoId, accountId, center.UnitChangeNoticeEvent, nil)
		req.Response(true)
	})
	// 科技升级
	_ = namespace.On(InfoScienceUp, func(req *nebula.Request, scienceId int) {
		fmt.Println("info science up", scienceId)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		account := controller.Center.GetData(mapNoId, cooperated.AccountType, accountId)
		// 根据科技能力，更新影响范围
		targetEffect, err := controller.UpgradeScience(req, scienceId, &user, account.(*cooperated.Account))
		if err != nil {
			req.ResponseErr(err)
			return
		}
		req.Response(true)
		targetType := []byte{}
		targetKey := [][]string{}
		for dataType, pm := range targetEffect {
			if dataType == cooperated.AccountType {
				continue
			}
			targetType = append(targetType, byte(dataType))
			keys := []string{}
			for id, _ := range pm {
				keys = append(keys, controller.Center.TargetKeyMap[dataType][id])
			}
			targetKey = append(targetKey, keys)
		}
		controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.Update, []interface{}{cooperated.AccountType, accountId, "science"})
		controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.DependUpdate, []interface{}{cooperated.AccountType, accountId, targetType, targetKey, "science"})
	})

	// 商店道具列表
	_ = namespace.On(InfoShopProps, func(req *nebula.Request, area string) {
		var shopProps []*model.ShopProp
		var ok bool
		shopProps, ok = controller.Center.ShopPropList[area]
		if !ok {
			req.ResponseErr(controller.Center.LanguageError("AREA_SHOP_ERROR"))
			return
		}
		req.SetCompress(true)
		req.Response(shopProps)
	})

	// 购买商店道具
	_ = namespace.On(InfoBuyShopProps, func(req *nebula.Request, shopPropId int, number int) {
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		mapNoId, accountId, _, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		account := controller.Center.GetData(mapNoId, cooperated.AccountType, accountId)
		if err := controller.BuyProp(req, shopPropId, number, &user, account.(*cooperated.Account)); err != nil {
			req.ResponseErr(err)
			return
		}
		req.Response(true)
	})

	// 建筑升级
	_ = namespace.On(InfoBuildUpgrade, func(req *nebula.Request, userBuildId int) {
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		account := controller.Center.GetData(mapNoId, cooperated.AccountType, accountId)

		build := controller.Center.GetData(mapNoId, cooperated.BuildType, userBuildId)
		buildKey := utils.ToString(build.GetProp(cooperated.Key))
		buildId := controller.Center.TargetIdMap[cooperated.BuildType][buildKey]
		if err := controller.ValidUpgradeBuild(req, utils.ToInt(build.GetProp(cooperated.Level)), buildId, &user, account.(*cooperated.Account), build.(*cooperated.Build)); err != nil {
			req.ResponseErr(err)
			return
		}

		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.Upgrade, []interface{}{cooperated.BuildType, userBuildId})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
	})
	// 建筑销毁
	_ = namespace.On(InfoBuildDestroy, func(req *nebula.Request, buildId int) {

		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}

		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.Destroy, []interface{}{cooperated.BuildType, buildId})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
	})
	// 使用指令
	_ = namespace.On(InfoUseDirect, func(req *nebula.Request, directId int, t byte, id string, params []interface{}) {

		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}

		direct, ok := controller.Center.DirectMap[directId]
		if !ok {
			req.ResponseErr(controller.Center.LanguageError("NOT_EXIST_DIRECT"))
			return
		}
		if direct.Mode == model.MainDirectMode || direct.Mode == model.AutoDirectMode {
			req.ResponseErr(controller.Center.LanguageError("NOT_MANUAL_DIRECT"))
			return
		}

		// 道具指令：验证道具数量
		prop, ok := controller.Center.PropWithDirectMap[directId]
		if ok {
			err := controller.ValidAndUseUnitProp(req, id, prop.Id, false)
			if err != nil {
				req.ResponseErr(err)
				return
			}
		}

		params, err = direct.Fill(params)
		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.UseDirect, []interface{}{t, id, directId, nil, nil, params})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
	})
	_ = namespace.On(InfoUseDirectWithTarget, func(req *nebula.Request, directId int, t byte, id string, targetT byte, targetId interface{}, params []interface{}) {
		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}

		direct, ok := controller.Center.DirectMap[directId]
		if !ok {
			req.ResponseErr(controller.Center.LanguageError("NOT_EXIST_DIRECT"))
			return
		}
		if direct.Mode == model.MainDirectMode || direct.Mode == model.AutoDirectMode {
			req.ResponseErr(controller.Center.LanguageError("NOT_MANUAL_DIRECT"))
			return
		}

		// 道具指令：验证道具数量
		prop, ok := controller.Center.PropWithDirectMap[directId]
		if ok {
			err := controller.ValidAndUseUnitProp(req, id, prop.Id, false)
			if err != nil {
				req.ResponseErr(err)
				return
			}
		}

		params, err = direct.Fill(params)
		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.UseDirect, []interface{}{t, id, directId, targetT, targetId, params})
		if result != nil {
			req.ResponseErr(result.(error))
			return
		}
		req.Response(true)
	})
	// 获取操作列表
	_ = namespace.On(InfoOperationList, func(req *nebula.Request, selectIds []interface{}, dt byte, id interface{}) {
		fmt.Println("operate list", selectIds, dt, id)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			req.ResponseErr(err)
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		mapInstance := controller.Center.GetMap(mapNoId)

		//var alliance int
		//if err := req.Get("alliance", &alliance); err != nil {
		//	return
		//}
		target := model.OperationShow(0)

		dataType := structure.PublicDataType(dt)
		// selectIds是默认指向部队
		multi := len(selectIds) > 1
		has := len(selectIds) > 0
		self := false
		if has && !multi {
			if dataType == cooperated.UnitType && selectIds[0] == id {
				self = true
			}
		}
		directMap := map[int][]*model.Direct{}
		var coolMap map[int]int64
		var ll []*model.Operation
		info := controller.Center.GetData(mapNoId, dataType, id)
		if dataType != cooperated.NodeType && info == nil {
			//req.ResponseErr(controller.Center.LanguageError("DIRECT_TARGET_MISS"))
			return
		}

		var position []byte
		if dataType == cooperated.NodeType {
			position = utils.ToBytes(id)
		}
		if position == nil || len(position) == 0 {
			position = utils.ToBytes(info.GetProp(cooperated.Position))
		}
		identity := info.ToInt(cooperate.Identity)
		if dataType == cooperated.NodeType {
			target = model.NeutralOperationShow
		} else {
			_, isEnemy := controller.TM.JudgeIdentity(selfIdentity, identity)
			//fmt.Println("identity", selfIdentity, identity, isEnemy)
			if isEnemy {
				target = model.EnemyOperationShow
			} else {
				target = model.FriendOperationShow
				otherAccount := utils.ToInt(info.GetProp(cooperated.AccountDataType))
				// 获取自己的联盟id和友盟id
				if accountId == otherAccount {
					target = model.SelfOperationShow
				}
			}
		}
		rKey := info.ToString(cooperated.Key)
		rid := controller.Center.TargetIdMap[dataType][rKey]
		rLevel := info.ToInt(cooperated.Level)
		if rKey != cooperate.DefaultKey {
			ll = append(ll, controller.Center.OperationLevels[info.GetDataType()][rKey]...)
		}
		// 加入该类型的基础操作
		ll = append(ll, controller.Center.OperationLevels[info.GetDataType()][cooperate.DefaultKey]...)
		if self {
			ll = controller.Center.OperationSelf
		}
		sort.Slice(ll, func(i, j int) bool {
			return ll[j].Operation.Weight > ll[i].Operation.Weight
		})
		// 获取选择的部队数据
		unitList := make([]*cooperated.Unit, len(selectIds))
		distanceList := make([]int, len(selectIds))
		if has {
			list := controller.Center.ListData(mapNoId, cooperated.UnitType, selectIds)
			if list == nil {
				req.ResponseErr(controller.Center.LanguageError("DIRECT_UNIT_MISS"))
				return
			}
			for index, t := range list {
				if t == nil {
					req.ResponseErr(controller.Center.LanguageError("DIRECT_UNIT_MISS"))
					return
				}
				unitList[index] = t.(*cooperated.Unit)
				distanceList[index] = mapInstance.Distance(unitList[index].GetPosition(), position)
				t.MergeProp(cooperated.Distance, distanceList[index])
			}
			// 获取部队的指令冷却时间
			if has && !multi {
				unit := unitList[0]
				abilityProp := cooperated.ReceiveAbilityProp(unit)
				//fmt.Println("direct", abilityProp.DirectIds)
				directIds := abilityProp.DirectIds
				coolMap = make(map[int]int64, len(directIds))
				// 将指令按操作id分组
				for index, id := range directIds {
					direct := controller.Center.DirectMap[id]
					dm, ok := directMap[direct.OperationId]
					if !ok {
						dm = []*model.Direct{}
					}
					dm = append(dm, direct)
					directMap[direct.OperationId] = dm
					coolMap[id] = abilityProp.DirectCool[index]
				}
			}
		}

		account := controller.Center.GetData(mapNoId, cooperated.AccountType, accountId)

		//fmt.Println("operate list", selectIds, has, multi, info.Data(), target, directMap)
		// 生成操作列表
		result := []*model.OperationInstance{}
		for _, ik := range ll {
			//fmt.Println("operate", ik)
			if !ik.Filter(target) && ik.Operation.UnitType != model.SelfUnitOperationType {
				continue
			}
			//fmt.Println("operate", ik.Id, 1)
			if !has && ik.Operation.NeedUnit {
				continue
			}

			if has {
				//fmt.Println("operate", ik.Id, 2)
				if multi && ik.Operation.UnitType != model.MultiUnitOperationType {
					// 多选部队，只能选多选部队
					continue
				}

				if !self && ik.Operation.UnitType == model.SelfUnitOperationType {
					// 自己部队
					// 当前非自己，则过滤自己类型
					continue
				}
			}

			//fmt.Println("operate", ik.Id, 3)
			if ik.Operation.Require != nil {
				if !controller.ValidRequire(req, ik.Require, &user, account.(*cooperated.Account), nil, nil) {
					continue
				}
			}
			if ik.Operation.TargetRequire != nil {
				if dataType == cooperated.UnitType {
					if !controller.ValidRequire(req, ik.TargetRequire, &user, nil, nil, info) {
						continue
					}
				} else if dataType == cooperated.BuildType {
					if !controller.ValidRequire(req, ik.TargetRequire, &user, nil, nil, info) {
						continue
					}
				}
			}
			//fmt.Println("operate", ik.Id, 4)
			if ik.Operation.DistanceRequire != nil && has {
				item := controller.Center.RelationGroupMap[ik.Operation.DistanceRequire.Id]

				c := 0
				for index, unit := range unitList {
					source := unit.ToInt(item.Key)
					if ik.Operation.DistanceRequire.Comp(source, distanceList[index]) {
						c += 1
					}
				}
				if c == 0 {
					continue
				}
			}
			//fmt.Println("operate", ik.Id, 5)
			if has && ik.UnitRequire != nil {
				c := 0
				for _, unit := range unitList {
					if controller.ValidRequire(req, ik.UnitRequire, &user, nil, nil, unit) {
						c += 1
					}
				}
				if c == 0 {
					continue
				}
			}
			//fmt.Println("operate", ik.Id, 6)
			if ik.Operation.Type == model.BaseOperationType {
				require, consume := controller.Center.SelectBindOperation(ik.Operation.RelationSelect, rid, dataType, rLevel)
				result = append(result, model.NewOperationInstance(ik, nil, 0, require, consume))
				continue
			}
			//fmt.Println("operate", ik.Id, 7)
			if ik.Operation.Type == model.DirectOperationType {
				dm, ok := directMap[ik.Id]
				if !ok {
					continue
				}

				for _, direct := range dm {
					if ik.Operation.DirectDistance {
						if direct.MaxDistance > 0 {
							c := 0
							for _, distance := range distanceList {
								if int(direct.MaxDistance) >= distance {
									c += 1
								}
							}
							if c == 0 {
								continue
							}
						} else {
							continue
						}
					}
					result = append(result, model.NewOperationInstance(ik, direct, coolMap[direct.Id], nil, nil))
				}
			}
		}
		//fmt.Println("operation list", result)
		req.Response(result)
	})
	// 执行操作
	_ = namespace.On(InfoOperate, func(req *nebula.Request, selectIds []interface{}, operateId int, params []interface{}) {
		fmt.Println("operate", selectIds, operateId, params)
		if operateId == 0 {
			req.ResponseErr(errors.New("操作id为空"))
			return
		}
		var err error
		operation := controller.Center.OperationMap[operateId]
		if operation.Type == model.DirectOperationType {
			// params第一个就是指令id
			directId := utils.ToInt(params[0])
			direct := controller.Center.DirectMap[directId]
			if direct == nil {
				req.ResponseErr(err)
				return
			}

			params, err = operation.FillDirect(direct, params)
		} else {
			params, err = operation.Fill(params)
		}
		if err != nil {
			req.ResponseErr(err)
			return
		}
		fmt.Println("operate result", params)
		// selectIds是默认指向部队
		has := len(selectIds) > 0
		if has {
			// 循环替换部队id
			targetIndex := -1
			for index, key := range operation.Params {
				if key == "unit_id" || key == "id" {
					targetIndex = index
				}

			}
			if targetIndex >= 0 {
				mapNoId, _, _, err := GetInfoQueryParam(req)
				if err != nil {
					req.ResponseErr(err)
					return
				}
				list := controller.Center.ListData(mapNoId, cooperated.UnitType, selectIds)
				if list == nil {
					req.ResponseErr(controller.Center.LanguageError("DIRECT_UNIT_MISS"))
					return
				}
				for _, t := range list {
					if t == nil {
						req.ResponseErr(controller.Center.LanguageError("DIRECT_UNIT_MISS"))
						return
					}
					if t.GetProp(cooperated.FortressDataType) != nil {
						req.ResponseErr(controller.Center.LanguageError("UNIT_IN_ROBOT"))
						return
					}
				}
				for _, id := range selectIds {
					params[targetIndex] = id

					rr, err := namespace.Trigger(nebula.NSE(operation.Operation.InfoEvent), params, req)
					if err != nil {
						req.ResponseErr(err)
					}
					req.Bind(rr)
				}
				return
			}
		}
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			req.ResponseErr(err)
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		ok, consumeData := controller.ValidConsume(req, operation.UseConsume, 1, &user, nil)
		if !ok {
			req.ResponseErr(ValidException("消耗不足，无法执行"))
			return
		}
		rr, err := namespace.Trigger(nebula.NSE(operation.Operation.InfoEvent), params, req)
		if err != nil {
			req.ResponseErr(err)
			rr.Release()
			return
		}
		if err := controller.UpdateConsume(req, consumeData, &user, nil); err != nil {
			req.ResponseErr(ValidException("消耗不足，无法执行"))
			rr.Release()
			return
		}
		req.Bind(rr)
	})
	// 获取当前账号可创建的部队列表
	_ = namespace.On(InfoCanUnitList, func(req *nebula.Request) {
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			req.ResponseErr(err)
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		mapNoId, accountId, _, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		account := controller.Center.GetData(mapNoId, cooperated.AccountType, accountId)
		unitList := make([]*model.UnitInfo, 0, len(controller.Center.CreateUnits))
		for _, unit := range controller.Center.CreateUnits {
			if !controller.ValidRequire(req, unit.FilterRequireSlice, &user, account, nil, nil) {
				continue
			}
			unitList = append(unitList, unit.Info)
		}
		req.Response(unitList)
	})
	// 获取当前账号可创建的部队列表
	_ = namespace.On(InfoCanUnitBuildList, func(req *nebula.Request, userUnitId string) {
		fmt.Println("unit build", userUnitId)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			req.ResponseErr(err)
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		mapNoId, accountId, _, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		account := controller.Center.GetData(mapNoId, cooperated.AccountType, accountId)

		userUnit := controller.Center.GetData(mapNoId, cooperated.UnitType, userUnitId)
		buildList := make([]*model.BuildInfo, 0, len(controller.Center.UnitBuilds))
		for _, build := range controller.Center.UnitBuilds {
			//fmt.Println("build", build.FilterRequireSlice)
			if !controller.ValidRequire(req, build.FilterRequireSlice, &user, account.(*cooperated.Account), nil, userUnit.(*cooperated.Unit)) {
				continue
			}
			buildList = append(buildList, build.Info)
		}
		req.Response(buildList)
	})

	// 创建建筑
	_ = namespace.On(InfoBuildCreate, func(req *nebula.Request, name string, buildId int, position []byte, direction []byte, mode byte, userUnitId string, attrId int) {
		fmt.Println("info build create", name, userUnitId, buildId, attrId)
		var userId int
		if err := req.Get("user_id", &userId); err != nil {
			return
		}
		var user model.User
		if err := controller.Center.GetUser(userId, &user); err != nil {
			req.ResponseErr(err)
			return
		}
		mapNoId, accountId, selfIdentity, err := GetInfoQueryParam(req)
		if err != nil {
			req.ResponseErr(err)
			return
		}
		key := controller.Center.TargetKeyMap[cooperated.BuildType][buildId]
		account := controller.Center.GetData(mapNoId, cooperated.AccountType, accountId)
		unit := controller.Center.GetData(mapNoId, cooperated.UnitType, userUnitId)
		if err := controller.ValidCreateBuild(req, buildId, &user, account, unit, false); err != nil {
			req.ResponseErr(err)
			return
		}

		result := controller.Center.Signal(mapNoId).OnQuery(accountId, selfIdentity, cooperated.CreateBuild, []interface{}{key, position, direction, mode, name, cooperated.UnitType, userUnitId, []interface{}{attrId}})
		if result != nil {
			switch r := result.(type) {
			case error:
				req.ResponseErr(r)
				return
			}
			req.Response(true)
		} else {
			req.Response(false)
		}
	})
}
